home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / font3d10.zip / build.cpp < prev    next >
C/C++ Source or Header  |  1994-09-15  |  18KB  |  552 lines

  1. //=================================================================================================
  2. //   Build.CPP
  3. //-------------------------------------------------------------------------------------------------
  4. //
  5. //   Copyright (c) 1994 by Todd A. Prater
  6. //   All rights reserved.
  7. //
  8. //=================================================================================================
  9.  
  10.  
  11. #include <stdlib.h>
  12. #include <fstream.h>
  13. #include "Config.H"
  14. #include "Vector.H"
  15. #include "TrueType.H"
  16. #include "Geometry.H"
  17. #include "Build.H"
  18.  
  19. #define IGNORE  2
  20. #define INSIDE  1
  21. #define OUTSIDE 0
  22.  
  23.  
  24.  
  25. //  ******************************************************
  26. //         NOTE:  Please excuse the debugging code
  27. //  ******************************************************
  28.  
  29.  
  30.  
  31. //===========================================================================================================
  32. //  PolygonizeContour                                                                                        
  33. //-----------------------------------------------------------------------------------------------------------
  34. //===========================================================================================================
  35.  
  36. void PolygonizeContour(TTFont&   font,
  37.                        USHORT  glyphnum,
  38.                        USHORT  contournum,
  39.                        USHORT  resolution,
  40.                        DOUBLE    depth,
  41.                        POLYGON&  polygon    )
  42. {
  43.  
  44.    ULONG  i,j;
  45.    ULONG  polyi;
  46.    ULONG  offcount,pointcount;
  47.    ULONG  consecutiveoffcount;
  48.    INT    lastwasoff;
  49.    INT    cur_type,prev_type,next_type;
  50.    VECTOR cp1,cp2,cp3,cur_point,prev_point,next_point;
  51.    DOUBLE cur_x,cur_y,prev_x,prev_y,next_x,next_y;
  52.    DOUBLE tstep;
  53.  
  54.    if (font.NumContours(glyphnum)<1)
  55.       return;
  56.  
  57.    if (contournum>=font.NumContours(glyphnum))
  58.       return;
  59.  
  60.    if(polygon.numpoints>0)
  61.    {
  62.       delete polygon.pointlist;
  63.       polygon.numpoints=0;
  64.    }
  65.  
  66.    lastwasoff=0; 
  67.    consecutiveoffcount=0; 
  68.    offcount=0;
  69.    for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
  70.    {
  71. //      if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE) cout<<i<<": ON"<<endl;
  72. //      else cout<<i<<": OFF"<<endl;
  73.       if(font.FontPointType(glyphnum,contournum,i)==OFF_CURVE)
  74.       {
  75.          offcount++;
  76.          if(lastwasoff)
  77.             consecutiveoffcount++;
  78.          lastwasoff=1;
  79.       }
  80.       else
  81.          lastwasoff=0;
  82.    }
  83.  
  84.    polygon.numpoints = font.NumPoints(glyphnum,contournum) + offcount*(resolution-2) + consecutiveoffcount;
  85.    polygon.pointlist = new VECTOR[polygon.numpoints+40];  // Temporary fix (give some playing room...)
  86.  
  87.    polyi=0;
  88.  
  89. //   pointcount = font.NumPoints(glyphnum,contournum);
  90.    for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
  91.    {
  92.  
  93.       if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE)
  94.       {
  95. //cout<<"OnCURVE: "<<i<<endl;
  96.          polygon.pointlist[polyi] = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
  97.                                     (DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
  98.          polyi++;
  99.       }
  100.       else
  101.       {
  102. //cout<<"OffCURVE:  "<<i<<endl;
  103.          if(font.FontPointType(glyphnum,contournum,i-1)==ON_CURVE)
  104.          {
  105.             cp1 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(),
  106.                         (DOUBLE)font.FontPointY(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(), depth);
  107.          }
  108.          else
  109.          {
  110.             cp1 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointX(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(),
  111.                         ((DOUBLE)font.FontPointY(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointY(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(), depth);
  112.          }
  113.  
  114.          cp2 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
  115.                      (DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
  116.  
  117.          if (i==(font.NumPoints(glyphnum,contournum)-1))
  118.          {
  119. //cout<<"THE LAST ONE"<<endl;
  120.             cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(),
  121.                         (DOUBLE)font.FontPointY(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(), depth);
  122.          }
  123.          else
  124.          {
  125.             if(font.FontPointType(glyphnum,contournum,i+1)==ON_CURVE)
  126.             {
  127.                cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(),
  128.                            (DOUBLE)font.FontPointY(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(), depth);
  129.                i++;
  130.             }
  131.             else
  132.             {
  133.                cp3 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i)+(DOUBLE)font.FontPointX(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(),
  134.                            ((DOUBLE)font.FontPointY(glyphnum,contournum,i)+(DOUBLE)font.FontPointY(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(), depth);
  135.             }
  136.          }
  137.  
  138.          tstep = 1.0/(DOUBLE)resolution;
  139.          for(j=0;j<resolution;j++)
  140.          {
  141.             polygon.pointlist[polyi] = ApproximateQuadraticSpline(cp1,cp2,cp3,tstep*(j+1));
  142.             polyi++;
  143.          }
  144.       }
  145.    }
  146.  
  147. if (   (polygon.pointlist[polyi-1].x==polygon.pointlist[0].x)
  148.     && (polygon.pointlist[polyi-1].y==polygon.pointlist[0].y))
  149. //cout<<"LAST IS FIRST"<<endl;
  150. polyi--;  //temporary fix....
  151. }
  152.  
  153.    polygon.numpoints = polyi;
  154.    polygon.orientation = polygon.findOrientation();
  155.  
  156. //cout<<polygon<<"P";
  157. }
  158.  
  159.  
  160.  
  161. //===========================================================================================================
  162. //  TriangulateFace                                                                                          
  163. //-----------------------------------------------------------------------------------------------------------
  164. //===========================================================================================================
  165.  
  166.  
  167. void TriangulateFace (TTFont&         font,
  168.                       USHORT        glyphnum,
  169.                       USHORT        resolution,
  170.                       DOUBLE           shrinkFactor,
  171.                       LIST<TRIANGLE>&  triangleList)
  172. {
  173.  
  174.  
  175.    int         i,j,k;
  176.    BOOLEAN     isAPair;
  177.    SHORT     contourCount;
  178.    POLYGON*    polyarray;
  179.    POLYGON*    shrunkpolyarray;
  180.    BYTEPTR*  relationship;
  181.  
  182. // cout<<"Beginning to triangulate..."<<endl;
  183.  
  184.    contourCount = font.NumContours(glyphnum);
  185.    if (contourCount<1) return;
  186.  
  187.    polyarray = new POLYGON[contourCount];
  188.    if (polyarray==NULL)
  189.    {
  190.       cout<<"ERROR: Out of memory."<<endl;
  191.       exit(1);
  192.    }
  193.  
  194.    shrunkpolyarray=new POLYGON[contourCount];
  195.    if (shrunkpolyarray==NULL)
  196.    {
  197.       cout<<"ERROR: Out of memory."<<endl;
  198.       exit(1);
  199.    }
  200.  
  201.    relationship = new BYTEPTR[contourCount];
  202.    if (relationship==NULL)
  203.    {
  204.       cout<<"ERROR: Out of memory."<<endl;
  205.       exit(1);
  206.    }
  207.    for (i=0;i<contourCount;i++)
  208.    {
  209.       relationship[i] = new BYTE[contourCount];
  210.       if (relationship[i]==NULL)
  211.       {
  212.          cout<<"ERROR: Out of memory."<<endl;
  213.          exit(1);
  214.       }
  215.    }
  216.  
  217.    for (i=0;i<contourCount;i++)
  218.    {
  219.       PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
  220.       if (shrinkFactor>0.0)
  221.          polyarray[i].Shrink(shrunkpolyarray[i],shrinkFactor);
  222.    }
  223.  
  224.  
  225.  
  226.  
  227. //cout<<"All Contours Polygonized."<<endl;
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.    for (i=0;i<contourCount;i++)
  236.       for (j=0;j<contourCount;j++)
  237.          if (i==j)
  238.             relationship[i][j]=IGNORE;
  239.          else if (polyarray[j].isInside(polyarray[i]))
  240.             relationship[i][j]=INSIDE;
  241.          else
  242.             relationship[i][j]=OUTSIDE;
  243.  
  244.  
  245.    for (i=0;i<contourCount;i++)
  246.    {
  247.       if (polyarray[i].orientation==CLOCKWISE)
  248.       {
  249.          for (j=0;j<contourCount;j++)
  250.          {
  251.             isAPair=FALSE;
  252.             if (relationship[i][j]==INSIDE && polyarray[j].orientation==COUNTER_CLOCKWISE)
  253.             {
  254.                isAPair=TRUE;
  255.                for (k=0;k<contourCount;k++)
  256.                {
  257.                   if (k==j || k==i || relationship[k][j]==IGNORE) continue;
  258.                   if (relationship[k][j]==INSIDE)
  259.                   {
  260.                      if (relationship[i][k]==INSIDE)
  261.                      {
  262.                         isAPair=FALSE;
  263.                         exit;
  264.                      }
  265.                   }
  266.                   else
  267.                      continue;
  268.                }
  269.             }
  270.             if (isAPair)
  271.             {
  272.                if (shrinkFactor>0.0)
  273.                  shrunkpolyarray[i].Combine(shrunkpolyarray[j]);
  274.                else
  275.                   polyarray[i].Combine(polyarray[j]);
  276.  
  277.                relationship[i][j]=IGNORE;
  278.             }
  279.          }
  280.       }
  281.    }
  282.  
  283.  
  284.    for (i=0;i<contourCount;i++)
  285.    {
  286.       if (polyarray[i].orientation==CLOCKWISE)
  287.       {
  288.          if (shrinkFactor>0.0)
  289.             shrunkpolyarray[i].Triangulate(triangleList);
  290.          else
  291.             polyarray[i].Triangulate(triangleList);
  292.       }
  293.    }
  294.  
  295.  
  296.    for (i=0;i<contourCount;i++)
  297.    {
  298.       delete polyarray[i].pointlist;
  299.       delete shrunkpolyarray[i].pointlist;
  300.       delete relationship[i];
  301.    }
  302.    delete polyarray;
  303.    delete shrunkpolyarray;
  304.    delete relationship;
  305.  
  306. }
  307.  
  308.  
  309.  
  310. //===========================================================================================================
  311. //  TriangulateEdges                                                                                         
  312. //-----------------------------------------------------------------------------------------------------------
  313. //===========================================================================================================
  314.  
  315.  
  316. void TriangulateEdges(TTFont&          font,
  317.                       USHORT           glyphnum,
  318.                       USHORT           resolution,
  319.                       DOUBLE           frontDepth,
  320.                       DOUBLE           backDepth,
  321.                       DOUBLE           angleThreshold,
  322.                       LIST<TRIANGLE>&  tlist)
  323. {
  324.  
  325.  
  326.    INT         i,j,k;
  327.    TRIANGLE*   t1;
  328.    TRIANGLE*   t2;
  329.    VECTOR      previous,current1,current2,next;
  330.    VECTOR      previousFacet,currentFacet,nextFacet;
  331.    VECTOR      previousFacetNormal,currentFacetNormal,nextFacetNormal;
  332.    VECTOR      averageNormal1,averageNormal2;
  333.    VECTOR      p1,p2,p3,p4;
  334.    ULONG       numberOfPoints;
  335.    SHORT       contourCount;
  336.    POLYGON*    polyarray;
  337.    VECTOR      zDir(0,0,1);
  338.    DOUBLE      angle1,angle2;
  339.    
  340.    contourCount = font.NumContours(glyphnum);
  341.    if (contourCount<1) return;
  342.  
  343.    polyarray = new POLYGON[contourCount];
  344.    if (polyarray==NULL)
  345.    {
  346.       cout<<"ERROR: Out of memory."<<endl;
  347.       exit(1);
  348.    }
  349.  
  350.    for (i=0;i<contourCount;i++)
  351.       PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
  352.  
  353.  
  354.  
  355.  
  356.    for (i=0;i<contourCount;i++)
  357.    {
  358.       numberOfPoints  = polyarray[i].numpoints;
  359.  
  360.       for (j=0;j<numberOfPoints;j++)
  361.       {
  362.  
  363.          if (j==numberOfPoints-2)
  364.          {
  365.             previous = polyarray[i].pointlist[j-1];
  366.             current1 = polyarray[i].pointlist[j];
  367.             current2 = polyarray[i].pointlist[j+1];
  368.             next     = polyarray[i].pointlist[0];
  369.          }
  370.          else if (j==numberOfPoints-1)
  371.          {
  372.             previous = polyarray[i].pointlist[j-1];
  373.             current1 = polyarray[i].pointlist[j];
  374.             current2 = polyarray[i].pointlist[0];
  375.             next     = polyarray[i].pointlist[1];
  376.          }
  377.          else if (j==0)
  378.          {
  379.             previous = polyarray[i].pointlist[numberOfPoints-1];
  380.             current1 = polyarray[i].pointlist[j];
  381.             current2 = polyarray[i].pointlist[j+1];
  382.             next     = polyarray[i].pointlist[j+2];
  383.          }
  384.          else
  385.          {
  386.             previous = polyarray[i].pointlist[j-1];
  387.             current1 = polyarray[i].pointlist[j];
  388.             current2 = polyarray[i].pointlist[j+1];
  389.             next     = polyarray[i].pointlist[j+2];
  390.          }
  391.  
  392.             
  393.          previousFacet = ~(current1-previous);
  394.          currentFacet  = ~(current2-current1);
  395.          nextFacet     = ~(next-current2);
  396.  
  397.          previousFacetNormal = zDir^previousFacet;
  398.          currentFacetNormal  = zDir^currentFacet;
  399.          nextFacetNormal     = zDir^nextFacet;
  400.  
  401.          angle1 = acos(previousFacetNormal%currentFacetNormal);
  402.          angle2 = acos(currentFacetNormal%nextFacetNormal);
  403.  
  404.          if (angle1<angleThreshold)
  405.             averageNormal1 = ~(previousFacetNormal+currentFacetNormal);
  406.          else
  407.             averageNormal1 = currentFacetNormal;
  408.  
  409.          if (angle2<angleThreshold)
  410.             averageNormal2 = ~(currentFacetNormal+nextFacetNormal);
  411.          else
  412.             averageNormal2 = currentFacetNormal;
  413.  
  414.          p1 = current1; p1.z=frontDepth;
  415.          p2 = current1; p2.z=backDepth;
  416.          p3 = current2; p3.z=frontDepth;
  417.          p4 = current2; p4.z=backDepth;
  418.  
  419.          t1 = new TRIANGLE(p1,p2,p3,averageNormal1,averageNormal1,averageNormal2);
  420.          if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  421.  
  422.          t2 = new TRIANGLE(p2,p3,p4,averageNormal1,averageNormal2,averageNormal2);
  423.          if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  424.  
  425.          tlist.Add(t1);
  426.          tlist.Add(t2);
  427.       }
  428.  
  429.    }
  430.  
  431.    delete polyarray;
  432.  
  433. }
  434.  
  435.  
  436.  
  437.  
  438.  
  439. //  This routine doesn't quite work yet.  Sometimes if the polygon is 'shrunk' too much,
  440. //  it can become self intersecting, which throws everything else off...
  441.  
  442. void TriangulateBevels(TTFont& font, INT code, INT resolution,
  443.                        DOUBLE frontDepth, DOUBLE backDepth,
  444.                        DOUBLE faceShrink, DOUBLE edgeShrink,
  445.                        LIST<TRIANGLE>& tlist)
  446. {
  447.    INT         i,j;
  448.    TRIANGLE*   t1;
  449.    TRIANGLE*   t2;
  450.    TRIANGLE*   t3;
  451.    TRIANGLE*   t4;
  452.    INT         glyphnum;
  453.    VECTOR       p1,p2,p3,p4,p5,p6,p7,p8;
  454.    SHORT     contourCount;
  455.    POLYGON*    frontFacePolyArray;
  456.    POLYGON*    frontEdgePolyArray;
  457.    POLYGON*    backFacePolyArray;
  458.    POLYGON*    backEdgePolyArray;
  459.  
  460.    glyphnum = font.CharacterMap(code);
  461.  
  462.    contourCount = font.NumContours(glyphnum);
  463.    if (contourCount<1) return;
  464.  
  465.    frontFacePolyArray = new POLYGON[contourCount];
  466.    if (frontFacePolyArray==NULL) {  cout<<"ERROR: Out of memory."<<endl; exit(1); }
  467.    frontEdgePolyArray = new POLYGON[contourCount];
  468.    if (frontEdgePolyArray==NULL) {  cout<<"ERROR: Out of memory."<<endl; exit(1); }
  469.    backFacePolyArray =  new POLYGON[contourCount];
  470.    if (backFacePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
  471.    backEdgePolyArray = new POLYGON[contourCount];
  472.    if (backEdgePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
  473.  
  474.    for (i=0;i<contourCount;i++)
  475.    {
  476.       PolygonizeContour(font,glyphnum,i,resolution,frontDepth,frontEdgePolyArray[i]);
  477.       PolygonizeContour(font,glyphnum,i,resolution,backDepth,backEdgePolyArray[i]);
  478.       frontEdgePolyArray[i].Shrink(frontFacePolyArray[i],faceShrink);
  479.       backEdgePolyArray[i].Shrink(backFacePolyArray[i],faceShrink);
  480.       frontEdgePolyArray[i].SetDepth(frontDepth-edgeShrink);
  481.       backEdgePolyArray[i].SetDepth(backDepth+edgeShrink);
  482.  
  483.       for (j=0;j<frontEdgePolyArray[i].numpoints-1;j++)
  484.       {
  485.          p1 = frontFacePolyArray[i].pointlist[j];
  486.          p2 = frontFacePolyArray[i].pointlist[j+1];
  487.          p3 = frontEdgePolyArray[i].pointlist[j];
  488.          p4 = frontEdgePolyArray[i].pointlist[j+1];
  489.          p5 = backEdgePolyArray[i].pointlist[j];
  490.          p6 = backEdgePolyArray[i].pointlist[j+1];
  491.          p7 = backFacePolyArray[i].pointlist[j];
  492.          p8 = backFacePolyArray[i].pointlist[j+1];
  493.  
  494.          cout<<"VECTORS: "<<p1<<p2<<p3<<p4<<p5<<p6<<p7<<p8<<endl;
  495.  
  496.          t1 = new TRIANGLE(p1,p3,p2);
  497.          if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  498.          t2 = new TRIANGLE(p2,p3,p4);
  499.          if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  500.          t3 = new TRIANGLE(p5,p7,p8);
  501.          if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  502.          t4 = new TRIANGLE(p5,p8,p6);
  503.          if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  504.  
  505.          tlist.Add(t1);
  506.          tlist.Add(t2);
  507.          tlist.Add(t3);
  508.          tlist.Add(t4);
  509.       }
  510.  
  511.       p1 = frontFacePolyArray[i].pointlist[j];
  512.       p2 = frontFacePolyArray[i].pointlist[0];
  513.       p3 = frontEdgePolyArray[i].pointlist[j];
  514.       p4 = frontEdgePolyArray[i].pointlist[0];
  515.       p5 = backEdgePolyArray[i].pointlist[j];
  516.       p6 = backEdgePolyArray[i].pointlist[0];
  517.       p7 = backFacePolyArray[i].pointlist[j];
  518.       p8 = backFacePolyArray[i].pointlist[0];
  519.  
  520.       t1 = new TRIANGLE(p1,p3,p2);
  521.       if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  522.       t2 = new TRIANGLE(p2,p3,p4);
  523.       if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  524.       t3 = new TRIANGLE(p5,p7,p8);
  525.       if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  526.       t4 = new TRIANGLE(p5,p8,p6);
  527.       if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
  528.  
  529.       tlist.Add(t1);
  530.       tlist.Add(t2);
  531.       tlist.Add(t3);
  532.       tlist.Add(t4);
  533.  
  534.    }
  535.  
  536.    for (i=0;i<contourCount;i++)
  537.    {
  538.       delete frontFacePolyArray[i].pointlist;
  539.       delete frontEdgePolyArray[i].pointlist;
  540.       delete backEdgePolyArray[i].pointlist;
  541.       delete backFacePolyArray[i].pointlist;
  542.    }
  543.    delete frontFacePolyArray;
  544.    delete frontEdgePolyArray;
  545.    delete backFacePolyArray;
  546.    delete backEdgePolyArray;
  547.  
  548. }
  549.  
  550.  
  551.